/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MetricsRetriever.RetrieverComponents;

import MetricsRetriever.RetrieverComponents.Parser;
import DataStructures.ProjectInformation;
import DataStructures.ProjectPackage;
import General.Globals;
import General.RequestMaker;
import java.text.DateFormat;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Manuel
 */
public class GCParser extends Parser{

   //TODO implement

    private ProjectInformation data;
    private String link;
    private String currentPage;

    public GCParser(){
        super();
    }

    public ProjectInformation getProjectInformation(String l){
        data = new ProjectInformation();
        this.link = l;
        currentPage = RequestMaker.getPage(link);
        data.setUrl(l);
        data.setForge(Globals.GOOGLECODE);
        data.setName(this.parseCharacterData("/p/","/",this.link,false,true));
        data.setDescription(this.parseCharacterData("<td id=\"wikicontent\" class=\"psdescription\">","</td>",this.currentPage,true,true));
        this.retrieveActivityLevel();
        this.retrieveArchieveLink();
        this.retrieveCollaborators();
        this.retrieveLabels();
        this.retrieveRepositoryLink();
        return data;
    }

    private void retrieveArchieveLink() {
        //parse the download page to find the right download links
        //list all downloads define algorithm to rank them
        String projectURL = data.getUrl() ;
        String projectName = data.getName();
        String link = "";
        ArrayList<ProjectPackage> candidateLinks = new ArrayList<ProjectPackage>();
        String downloadsPage = RequestMaker.getPage(projectURL+"downloads/list?can=1&colspec=Filename+Summary+Uploaded+Size+DownloadCount");
        if(downloadsPage.isEmpty())
            return;
        //detect in which column in which the size of the file is given
        String sizeColumn = "4";
        int colStartIndex = downloadsPage.indexOf("var _allColumnNames = [");
        int colEndIndex = downloadsPage.toLowerCase().indexOf("size",colStartIndex);
        if(colStartIndex > -1 && colEndIndex > -1){
            String columns = downloadsPage.substring(colStartIndex,colEndIndex);
            sizeColumn = Integer.toString(columns.replaceAll("[^,]", "").length());
        }

        //detect the column in which the number of downloads is given

        String countColumn = "5";
        int couStartIndex = downloadsPage.indexOf("var _allColumnNames = [");
        int couEndIndex = downloadsPage.toLowerCase().indexOf("downloadcount",couStartIndex);
        if(couStartIndex > -1 && couEndIndex > -1){
            String columns = downloadsPage.substring(couStartIndex,couEndIndex);
            countColumn = Integer.toString(columns.replaceAll("[^,]", "").length());
        }

        //       N   O   W             R   E    T  R   I   E    V   E            A L L         L I N K S
        //cut out relevant part of html
        downloadsPage = parseCharacterData("id=\"resultstable\" width=\"100%\">","</table>",downloadsPage,false,true);

        //check through all links and retrieve user id
        ProjectPackage currentPackage;
        int instances = 0;
        long totalSize = 0;
        int avgSize = 0;
        long totalDownloads = 0;
        int avgDownloads = 1;
        String typeTag ="";
        int nextLink = downloadsPage.indexOf("href=");
        String originalPage = downloadsPage;
        downloadsPage = downloadsPage.toLowerCase();

        while(nextLink >= 0){
            currentPackage = new ProjectPackage(projectName);
            int nextRef = downloadsPage.indexOf("\"", nextLink) + 1;
            int endRef = downloadsPage.indexOf("\"", nextRef);
            int nextTypeTag = downloadsPage.indexOf("onclick",endRef);
            int endTypeTag = downloadsPage.indexOf("\"",nextTypeTag + 10);
            int endOfLink = downloadsPage.indexOf("</tr>",nextRef);

            // get the name
            if(nextRef>0 && endRef > 0)
                currentPackage.setName(originalPage.substring(nextRef,endRef));



            //check link and eventually add it to the list
            boolean isInterestingLink =  currentPackage.getName().endsWith(".tar.bzip2") || currentPackage.getName().endsWith(".tbz2") || currentPackage.getName().endsWith(".tar.bz2") || currentPackage.getName().endsWith(".tar.gzip") || currentPackage.getName().endsWith(".tgz") || currentPackage.getName().endsWith(".tar.gz") || currentPackage.getName().endsWith("zip") || currentPackage.getName().endsWith(".tar") || currentPackage.getName().endsWith(".jar") || currentPackage.getName().endsWith(".class");

            if(isInterestingLink){
                    //get the description
                    if(nextTypeTag>0 && endTypeTag>0)
                        typeTag = downloadsPage.substring(nextTypeTag,endTypeTag);
                    String description = parseCharacterData("href=","</tr>",downloadsPage,true,true);
                    currentPackage.setDescription(description);

                    //set the featuring
                    if(typeTag.contains("featured"))
                        currentPackage.setFeatured(true);

                    //get the size
                    String size = parseCharacterData("<td class=\"vt col_"+sizeColumn+"\"","</td>",downloadsPage,true,false);
                    size = size.replaceAll(" ", "");
                    long sizeNo = 0;
                    if(size.contains("mb")){
                        double dec = Double.parseDouble(size.replaceAll("mb", ""));
                        dec *= 1000000;
                        sizeNo = Math.round(dec);
                    }
                    else if(size.contains("kb")){
                        double dec = Double.parseDouble(size.replaceAll("kb", ""));
                        dec *= 1000;
                        sizeNo = Math.round(dec);
                    }
                    else if(size.contains("bytes"))
                        sizeNo = (long) Integer.parseInt(size.replaceAll("bytes", ""));
                    currentPackage.setSize(sizeNo);

                    //get the number of downloads
                    String downloadString = parseCharacterData("<td class=\"vt col_"+countColumn+"\"","</td>",downloadsPage,true,false).replaceAll( "[^\\d]", "" );

                    int downloads = -1;
                    if(!downloadString.isEmpty()){
                        downloads = (int) Integer.parseInt(downloadString.replaceAll(" ", ""));
                    }
                    currentPackage.setDownloadNumber(downloads);

                    //get the date
                    String filteredName = currentPackage.getName().substring(currentPackage.getName().lastIndexOf("/")+1);
                    String pageDate = RequestMaker.getPage("http://code.google.com/p/"+projectName+"/downloads/detail?name="+filteredName);
                    if(pageDate.isEmpty())
                        return;
                    String theDate = parseCharacterData("<span class=\"date\" style=\"white-space:nowrap\"","</span>",pageDate,true,false);
                    if(theDate.contains("title")){
                        theDate = theDate.substring(theDate.indexOf(">")+1,theDate.length());
                    }
                    DateFormat df = DateFormat.getDateInstance();
                    Date myDate = null;
                    try {
                        myDate = df.parse(theDate);
                    } catch (ParseException ex) {
                        myDate = ProjectPackage.DEFAULT_DATE;
                    }
                    if(myDate == null){

                    }
                    currentPackage.setDate(myDate);


                    //add to the list if sufficient data is obtainable
                    if(myDate != null && currentPackage.getDownloadNumber() != -1 ){
                        instances++;
                        totalSize += currentPackage.getSize();
                        totalDownloads += currentPackage.getDownloadNumber();
                        candidateLinks.add(currentPackage);
                    }
            }

            downloadsPage = downloadsPage.substring(downloadsPage.indexOf("</tr>",endRef));
            originalPage = originalPage.substring(originalPage.indexOf("</tr>",endRef));
            nextLink = downloadsPage.indexOf("href=");

        }

        //identifying the most probable package
        if(instances != 0){
            avgSize = (int) (totalSize / instances);
            avgDownloads = (totalDownloads == 0) ? 1 : (int) (totalDownloads / instances);
        }

        ProjectPackage winner = null;
        int maxScore = -100000;
        Date maxDate = new Date(1,1,0);
        for(int i = 0;i<candidateLinks.size();i++){
            candidateLinks.get(i).rank(avgSize,avgDownloads);
            ProjectPackage pp = candidateLinks.get(i);
            if(pp.getRank()>maxScore){
                winner = pp;
                maxScore = pp.getRank();
                maxDate = pp.getDate();
            }
            if(pp.getRank()==maxScore && pp.getDate().after(maxDate)){
                winner = pp;
                maxDate = pp.getDate();
            }
        }
        if(winner != null)
            winner.setName("http:"+winner.getName());
        data.setArchieveLink(winner);
    }




    //SUBMETHODS FOR RETRIEVAL OF CONTEXTUAL INFORMATION
    private void retrieveLabels() {
        String labelString = this.parseCharacterData("<b>Labels</b><br/>",  "</span>",this.currentPage,true,true);
        labelString = labelString.replaceAll(" ","");
        ArrayList<String> labels = new ArrayList<String>();

        while(labelString.indexOf(",") != -1 ){
            labels.add(labelString.substring(0,labelString.indexOf(",")));
            labelString = labelString.substring(labelString.indexOf(",")+1);
        }
        String currentLabel;
        for(int i = labels.size()-1;i>=0;i--){
            currentLabel = labels.get(i).toLowerCase();
            data.addLabel(currentLabel);
            if(currentLabel.equals("java"))
                data.addLanguage(currentLabel);
            else if(currentLabel.contains("cpp") || currentLabel.contains("cplusplus") || currentLabel.contains("c++") )
                data.addLanguage("cplusplus");
        
        }
    }

    private void retrieveCollaborators() {

        String userPage = RequestMaker.getPage(link+"people/list");

        //cut out relevant part of html
        userPage = parseCharacterData("<b>Project People</b>","</tbody>",userPage,false,true);

        //check through all links and retrieve user id
        String currentCollaborator = "";
        int nextLink = userPage.indexOf("href=\"");
        String backup = userPage;
        userPage = userPage.toLowerCase();

        while(nextLink >= 0){
            int nextRef = userPage.indexOf("\"", nextLink) + 1;
            int endRef = userPage.indexOf("\"", nextRef);
            if(nextRef < 0 || endRef < 0)
                break;
            currentCollaborator = backup.substring(nextRef,endRef);
            int colStart = currentCollaborator.indexOf("/people/detail?u=");
            int tagLength = "/people/detail?u=".length();
            if(colStart < 0 )
                break;
            currentCollaborator = currentCollaborator.substring(colStart+tagLength);
            int startEmail = backup.indexOf(">",endRef) +1;
            int endEmail = backup.indexOf("<",startEmail);
            String collaboratorMail = backup.substring(startEmail,endEmail).replaceAll(" ", "");
            userPage = userPage.substring(endRef);
            backup = backup.substring(endRef);
            nextLink = userPage.indexOf("href=\"");
            data.addCollaboratorIfNew(currentCollaborator, collaboratorMail);
        }

    }

    private void retrieveActivityLevel(){
        String level = this.parseCharacterData("class=\"activity-level-", "\"", this.currentPage,true,true);
        if(level.equals("high"))
            data.setActivity(3);
        else if(level.equals("medium"))
            data.setActivity(2);
        else if(level.equals("low"))
            data.setActivity(1);
        else
            data.setActivity(0);
    }

    private void retrieveRepositoryLink(){
        String repoLink = null;
        String repoPage = RequestMaker.getPage(link+"source/checkout");

        // if it is SVN
        if(repoPage.contains("svn checkout")){
            data.setRepositoryType(Globals.SVN);
            String command = this.parseCharacterData("svn checkout", "</tt>", repoPage, true, true);
            int startIndex = command.indexOf("http");
            int endIndex = command.indexOf(" ",startIndex);
            String url = command.substring(startIndex,endIndex);
            repoLink = url;
        }

        //if it is CVS
        if(repoPage.contains("cvs -d")){
            data.setRepositoryType(Globals.CVS);
            //...
            
        }

        data.setRepositoryLink(repoLink);
    }

}
